﻿using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace NinjaToolbox.PhysicsSystem
{
    [CustomEditor(typeof(PhysicsObject))]
    [CanEditMultipleObjects]
    public class PhysicsObjectInspector : Editor
    {
        bool mIsEnabledDebugSettings;

        PhysicsShapeContainerDrawer mPhysicsShapeContainerDrawer;
        PhysicsShapeContainerDrawer PhysicsShapeContainerDrawer
        {
            get
            {
                if (mPhysicsShapeContainerDrawer == null)
                {
                    mPhysicsShapeContainerDrawer = new PhysicsShapeContainerDrawer();
                    mPhysicsShapeContainerDrawer.Initialization((target as PhysicsObject).PhysicsShapeContainer);
                }

                return mPhysicsShapeContainerDrawer;
            }
        }

        string[] mCachePhysicsLayerConstNames;

        bool mShapeIsUnfold;
        bool mOtherSettingsIsUnfold;
        bool mGroundSettingsIsUnfold;
        bool mGravitySettingsIsUnfold;
        bool mFallingHeadFixSettingsIsUnfold;

        bool mIsDrawerChanged;


        void Awake()
        {

        }

        void OnDestroy()
        {
            if (mPhysicsShapeContainerDrawer != null)
                mPhysicsShapeContainerDrawer.Dispose();
        }

        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            var physicsShapeContainer = serializedObject.FindProperty("mPhysicsShapeContainer");

            var layerProp = serializedObject.FindProperty("mLayer");
            var layerConstInfoProp = serializedObject.FindProperty("mLayerConstInfo");

            var virtualRayLengthProp = serializedObject.FindProperty("otherSettings.virtualRayLength");
            var movingEpsProp = serializedObject.FindProperty("otherSettings.movingEps");
            var movingDetectTimeSpacingProp = serializedObject.FindProperty("otherSettings.movingDetectTimeSpacing");
            var fallingHeadFixEpsProp = serializedObject.FindProperty("otherSettings.fallingHeadFixEps");
            var updateMovingDetectProp = serializedObject.FindProperty("otherSettings.updateMovingDetect");
            var isActivityObjectProp = serializedObject.FindProperty("otherSettings.isAcitivityObject");
            var optmizeModeProp = serializedObject.FindProperty("otherSettings.optimizeMode");
            var gravityMoveStepProp = serializedObject.FindProperty("otherSettings.gravityMoveStep");
            var gravityDeepIterateCountProp = serializedObject.FindProperty("otherSettings.gravityDeepIterateCount");
            var enabledBvhQueryProp = serializedObject.FindProperty("otherSettings.enabledBvhQuery");
            var groundBvhIDProp = serializedObject.FindProperty("otherSettings.groundBvhID");
            var wallBvhIDProp = serializedObject.FindProperty("otherSettings.wallBvhID");
            var registOrderProp = serializedObject.FindProperty("otherSettings.registOrder");

            var groundSettings_EnableProp = serializedObject.FindProperty("groundSettings.enabled");
            var groundSettings_useFootPointProp = serializedObject.FindProperty("groundSettings.useFootPoint");
            var groundSettings_footPointsProp = serializedObject.FindProperty("groundSettings.footPoints");
            var groundSettings_footPointsRelativeOffsetProp = serializedObject.FindProperty("groundSettings.footPointsRelativeOffset");
            var groundSettings_groundLayerConstInfoProp = serializedObject.FindProperty("groundSettings.groundLayerConstInfo");
            var groundSettings_groundLayerProp = serializedObject.FindProperty("groundSettings.groundLayer");
            var groundSettings_groundDetectLineLengthProp = serializedObject.FindProperty("groundSettings.groundDetectLineLength");

            var gravitySettings_EnableProp = serializedObject.FindProperty("gravitySettings.enabled");
            var gravitySettings_PresetProp = serializedObject.FindProperty("gravitySettings.preset");
            var gravitySettings_GravityAcceProp = serializedObject.FindProperty("gravitySettings.gravityAcce");
            var gravitySettings_GravityAcceScaleProp = serializedObject.FindProperty("gravitySettings.gravityAcceScale");
            var gravitySettings_GravityAcceLimitProp = serializedObject.FindProperty("gravitySettings.gravityAcceLimit");
            var gravitySettings_GravityScaleProp = serializedObject.FindProperty("gravitySettings.gravityScale");

            var fallingHeadFixSettings_EnableProp = serializedObject.FindProperty("fallingHeadFixSettings.enabled");
            var fallingHeadFixSettings_FixCenterOffsetPointProp = serializedObject.FindProperty("fallingHeadFixSettings.fixCenterOffsetPoint");
            var fallingHeadFixSettings_GradientProp = serializedObject.FindProperty("fallingHeadFixSettings.gradient");
            var fallingHeadFixSettings_RadiusProp = serializedObject.FindProperty("fallingHeadFixSettings.radius");
            var fallingHeadFixSettings_MinSpeedProp = serializedObject.FindProperty("fallingHeadFixSettings.minSpeed");
            var fallingHeadFixSettings_MaxSpeedProp = serializedObject.FindProperty("fallingHeadFixSettings.maxSpeed");
            var fallingHeadFixSettings_SpeedAreaTopExternProp = serializedObject.FindProperty("fallingHeadFixSettings.speedAreaTopExtern");
            var fallingHeadFixSettings_speedAreaBottomExternProp = serializedObject.FindProperty("fallingHeadFixSettings.speedAreaBottomExtern");

            var isDrawGizmosProp = serializedObject.FindProperty("isDrawGizmos");
            var alwaysVisibleGizmosProp = serializedObject.FindProperty("alwaysVisibleGizmos");

            using (var changeCheck = new EditorGUI.ChangeCheckScope())
            {
                mShapeIsUnfold = EditorGUILayout.Foldout(mShapeIsUnfold, "CollisionSettings");
                if (mShapeIsUnfold)
                {
                    EditorGUI.indentLevel++;

                    if (layerConstInfoProp.objectReferenceValue != null)
                    {
                        layerProp.intValue = PhysicsLayerDrawer.Draw("Layer Const Info", layerConstInfoProp, layerProp.intValue, ref mCachePhysicsLayerConstNames);
                    }
                    else
                    {
                        EditorGUILayout.PropertyField(layerConstInfoProp, new GUIContent("Layer Const Info"));
                        EditorGUILayout.PropertyField(layerProp, new GUIContent("Layer"));
                    }

                    PhysicsShapeContainerDrawer.DrawProperty(physicsShapeContainer, targets.Length > 1);

                    EditorGUILayout.PropertyField(isActivityObjectProp);
                    EditorGUILayout.PropertyField(optmizeModeProp);
                    EditorGUI.indentLevel--;
                }

                mGroundSettingsIsUnfold = EditorGUILayout.Foldout(mGroundSettingsIsUnfold, "GroundSettings");
                if (mGroundSettingsIsUnfold)
                {
                    EditorGUI.indentLevel++;
                    EditorGUILayout.PropertyField(groundSettings_EnableProp);

                    using (new EditorGUI.DisabledGroupScope(!groundSettings_EnableProp.boolValue))
                    {
                        EditorGUILayout.PropertyField(groundSettings_useFootPointProp);

                        using (new EditorGUI.DisabledGroupScope(!groundSettings_useFootPointProp.boolValue))
                        {
                            EditorGUILayout.PropertyField(groundSettings_footPointsProp, true);
                        }

                        using (new EditorGUI.DisabledGroupScope(groundSettings_useFootPointProp.boolValue))
                        {
                            EditorGUILayout.PropertyField(groundSettings_footPointsRelativeOffsetProp, true);
                        }

                        if (groundSettings_groundLayerConstInfoProp.objectReferenceValue != null)
                        {
                            groundSettings_groundLayerProp.intValue = PhysicsLayerDrawer.Draw("Ground Layer Const Info", groundSettings_groundLayerConstInfoProp, groundSettings_groundLayerProp.intValue, ref mCachePhysicsLayerConstNames);
                        }
                        else
                        {
                            EditorGUILayout.PropertyField(groundSettings_groundLayerConstInfoProp);
                            EditorGUILayout.PropertyField(groundSettings_groundLayerProp);
                        }

                        EditorGUILayout.PropertyField(groundSettings_groundDetectLineLengthProp);
                    }
                    EditorGUI.indentLevel--;
                }

                mGravitySettingsIsUnfold = EditorGUILayout.Foldout(mGravitySettingsIsUnfold, "GravitySettings");
                if (mGravitySettingsIsUnfold)
                {
                    EditorGUI.indentLevel++;
                    EditorGUILayout.PropertyField(gravitySettings_EnableProp);

                    using (new EditorGUI.DisabledGroupScope(!gravitySettings_EnableProp.boolValue))
                    {
                        EditorGUILayout.PropertyField(gravitySettings_PresetProp);

                        using (new EditorGUI.DisabledGroupScope(gravitySettings_PresetProp.objectReferenceValue != null))
                        {
                            EditorGUILayout.PropertyField(gravitySettings_GravityAcceProp);
                            EditorGUILayout.PropertyField(gravitySettings_GravityAcceScaleProp);
                            EditorGUILayout.PropertyField(gravitySettings_GravityAcceLimitProp);
                            EditorGUILayout.PropertyField(gravitySettings_GravityScaleProp);
                        }
                    }
                    EditorGUI.indentLevel--;
                }

                mFallingHeadFixSettingsIsUnfold = EditorGUILayout.Foldout(mFallingHeadFixSettingsIsUnfold, "FallingHeadFixSettings");
                if (mFallingHeadFixSettingsIsUnfold)
                {
                    EditorGUI.indentLevel++;
                    EditorGUILayout.PropertyField(fallingHeadFixSettings_EnableProp);

                    using (new EditorGUI.DisabledGroupScope(!fallingHeadFixSettings_EnableProp.boolValue))
                    {
                        EditorGUILayout.PropertyField(fallingHeadFixSettings_FixCenterOffsetPointProp);
                        EditorGUILayout.PropertyField(fallingHeadFixSettings_GradientProp);
                        EditorGUILayout.PropertyField(fallingHeadFixSettings_RadiusProp);
                        EditorGUILayout.PropertyField(fallingHeadFixSettings_MinSpeedProp);
                        EditorGUILayout.PropertyField(fallingHeadFixSettings_MaxSpeedProp);
                        EditorGUILayout.PropertyField(fallingHeadFixSettings_SpeedAreaTopExternProp);
                        EditorGUILayout.PropertyField(fallingHeadFixSettings_speedAreaBottomExternProp);
                    }
                    EditorGUI.indentLevel--;
                }

                mOtherSettingsIsUnfold = EditorGUILayout.Foldout(mOtherSettingsIsUnfold, "OtherSettings");
                if (mOtherSettingsIsUnfold)
                {
                    EditorGUI.indentLevel++;
                    EditorGUILayout.PropertyField(virtualRayLengthProp);
                    EditorGUILayout.PropertyField(movingEpsProp);
                    EditorGUILayout.PropertyField(movingDetectTimeSpacingProp);
                    EditorGUILayout.PropertyField(fallingHeadFixEpsProp);
                    EditorGUILayout.PropertyField(gravityMoveStepProp);
                    EditorGUILayout.PropertyField(gravityDeepIterateCountProp);
                    EditorGUILayout.PropertyField(updateMovingDetectProp);
                    EditorGUILayout.PropertyField(enabledBvhQueryProp);
                    EditorGUILayout.PropertyField(groundBvhIDProp);
                    EditorGUILayout.PropertyField(wallBvhIDProp);
                    EditorGUILayout.PropertyField(registOrderProp);
                    EditorGUI.indentLevel--;
                }

                EditorGUILayout.PropertyField(isDrawGizmosProp);
                EditorGUILayout.PropertyField(alwaysVisibleGizmosProp);

                if (changeCheck.changed)
                {
                    GUI.changed = true;
                    serializedObject.ApplyModifiedProperties();
                }
            }
        }

        public override bool HasPreviewGUI()
        {
            return true;
        }

        public override GUIContent GetPreviewTitle()
        {
            return new GUIContent("Physics Object Debug Information");
        }

        public override void OnPreviewGUI(Rect r, GUIStyle background)
        {
            var concertPhysicsObject = base.target as PhysicsObject;

            var y = r.y;
            EditorGUI.LabelField(new Rect(r.x, y, r.width, 20), "IsOnGround: " + concertPhysicsObject.IsOnGround, EditorStyles.whiteLabel);
            y += 20;
            EditorGUI.LabelField(new Rect(r.x, y, r.width, 20), "IsMoving: " + concertPhysicsObject.IsMoving, EditorStyles.whiteLabel);
            y += 20;
            EditorGUI.LabelField(new Rect(r.x, y, r.width, 20), "IsRising: " + concertPhysicsObject.IsRising, EditorStyles.whiteLabel);
            y += 20;
            EditorGUI.LabelField(new Rect(r.x, y, r.width, 20), "IsFalling: " + concertPhysicsObject.IsFalling, EditorStyles.whiteLabel);
            y += 20;
            EditorGUI.LabelField(new Rect(r.x, y, r.width, 20), "Velocity: " + concertPhysicsObject.Velocity, EditorStyles.whiteLabel);
        }
    }
}
